// -------------------
// DEBUG MODE
//#define DEBUG_SER
#define LED_ENABLE

// -------------------
// -- INTERFACE

//#define HAS_BGTEMPSENSOR

// --------------------
// --  ETC

/* Constant */
#ifdef LED_ENABLE
#define LED_DLY 50
#endif

// --------------------
// --  RS-485

/* Pinout */
#define CTR_485 9
#ifdef LED_ENABLE
#define LED_485 8
#endif

#ifndef LED_ENABLE
#define LED_DBG 8
#endif

/* Constant */
#define RX485 0
#define TX485 1

void set485Mode(char mode){
    if (mode) {
        digitalWrite(CTR_485, HIGH);
        #ifdef LED_ENABLE
        digitalWrite(LED_485, LOW);
        #endif
    } else {
        digitalWrite(CTR_485, LOW);
        #ifdef LED_ENABLE
        digitalWrite(LED_485, HIGH);  
        #endif
    }
}

void init485(){
    pinMode(CTR_485, OUTPUT);   
    #ifdef LED_ENABLE
    pinMode(LED_485, OUTPUT); 
    #endif
    for (int i=0; i < 4; ++i){
        set485Mode(TX485);
        #ifdef LED_ENABLE
        delay(LED_DLY);
        #endif
        set485Mode(RX485);
        #ifdef LED_ENABLE
        delay(LED_DLY);
        #endif
    }  
}

// -------------------
// LCD
#include <LiquidCrystal.h>

/* Pinout */
#define LCD_RS 7
#define LCD_EN 6
#define LCD_D4 5 
#define LCD_D5 4 
#define LCD_D6 3
#define LCD_D7 2

/* Constant */
#define LCD_COL 16
#define LCD_ROW 2

LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);

void initLCD(){
    lcd.begin(LCD_COL, LCD_ROW);
}
/*void clearLnLCD(int line){
    lcd.setCursor(0,line);
    for (int i = 0; i < LCD_COL; ++i) {
        lcd.write(' ');
    }
}*/


// -------------------
// Keypad

/* Pinout */
#define KP_R1 10
#define KP_R2 11
#define KP_R3 12
#define KP_R4 13
#define KP_C1 14
#define KP_C2 15
#define KP_C3 16
#define KP_C4 17

/* Constant */
#define DEBOUNCING_DLY 50
#define KEYPAD_DLY_us 100

#define KP_EMPTY 0

const byte ROWS = 4; 
const byte COLS = 4; 
char keys[ROWS][COLS] = {
    {'1','2','3','A'},
    {'4','5','6','B'},
    {'7','8','9','C'},
    {'*','0','#','D'}};

byte rowPins[ROWS] = {KP_R1, KP_R2, KP_R3, KP_R4};
byte colPins[COLS] = {KP_C1, KP_C2, KP_C3, KP_C4};

unsigned long long KPLastTime; 
char KPLastKey;

void initKeypad(){
    KPLastTime = 0;
    KPLastKey = 0;
    
    for (int i = 0; i < ROWS; ++i){
        pinMode(rowPins[i], OUTPUT);
    }

    for (int i = 0; i < COLS; ++i){
        pinMode(colPins[i], INPUT);
        digitalWrite(colPins[i], HIGH);
    }
}

char getKey(){
    if (millis() > KPLastTime + DEBOUNCING_DLY) {
        for (int p= 0; p < ROWS; ++p){
            for(int q= 0; q < ROWS; ++q){
                digitalWrite(rowPins[q],HIGH);
            }
            digitalWrite(rowPins[p],LOW);
            delayMicroseconds(KEYPAD_DLY_us);
            for (int r= 0; r < COLS; ++r){
                if (digitalRead(colPins[r])==LOW){                    
                    char nowChecking = keys[p][r];
                    if (KPLastKey != nowChecking){
                        KPLastTime = millis() ;
                        KPLastKey = nowChecking;
                        return nowChecking;
                    } else { 
                        return KP_EMPTY;
                    }
                }
            }
        }
        KPLastKey = KP_EMPTY;
        return KP_EMPTY;
    } else {
        return KP_EMPTY;
    }
}



void setup() {
    // ----------
    // -- INIT SERIAL
    Serial.begin(115200); 
    #ifdef DEBUG_SER
        Serial.println("Hello");
    #endif
    
    // ----------
    // -- INIT 485
    init485();
    set485Mode(RX485);
    
    // ----------
    // -- INIT LCD
    initLCD();

    // ----------
    // -- INIT Keypad
    initKeypad();

    // ----------
    // -- LED 
    #ifndef LED_ENABLE
    pinMode(LED_DBG, OUTPUT); 
    for (int i=0; i<4; ++i){
        digitalWrite(LED_DBG, LOW);
        delay(200);
        digitalWrite(LED_DBG, HIGH);  
        delay(200);
    }
    #endif
    
    idProg_CreateMenu();
}

void loop() {
    idProg_loop();
}

